﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using PuSuoPai;
using ServiceStack.Redis;
using ServiceStack.Redis.Generic;
using System.Threading;

namespace TeZhanDui
{
    public enum ROOM_STATE
    {
        WAITING,
        COUNT_DOWN,
        IN_GAME,

        MAX
    }

    public class Room
    {
        public int roomId { get; set; }
        public ROOM_TYPE type { get; set; }
        public ROOM_STATE state { get; set; }
        public Position[] positions { get; set; }
        public int playerCount { get; set; }
        Timer countDownTimer = null;
        public int countDownTimerCount { get; set; }
        int[] heartbeat;
        public Game game { get; set; }
        
        public Room()
        {
            roomId = -1;
            type = ROOM_TYPE.ROOM_GAME;
            state = ROOM_STATE.WAITING;
            positions = new Position[6];
            for (int i = 0; i < 6; i++)
            {
                positions[i] = new Position();
                positions[i].positionId = i;
            }
            playerCount = 0;
            countDownTimerCount = 8;//init value 8 second
            heartbeat = new int[6] { 0, 0, 0, 0, 0, 0};
            game = null;
        }

        void ResetHeartbeat()
        {
            for (int i = 0; i < 6; i++)
            {
                heartbeat[i] = 0;
            }
        }

        void StartCountDown()
        {
            countDownTimer = new Timer(CountDownTimerMethod, null, 1000, 1000);
            countDownTimerCount = 8;
            state = ROOM_STATE.COUNT_DOWN;
            ResetHeartbeat();
        }

        void UpdateHeartbeat(string usrId)
        {
            for (int i = 0; i < 6; i++)
            {
                if (positions[i].player != null && positions[i].player.Id.Equals(usrId))
                {
                    heartbeat[i]++;
                }
            }
        }

        Boolean CheckHeartbeat()
        {
            //for test sake
            return true;
            int kick = 0;
            for (int i = 0; i < 6; i++)
            {
                if (positions[i].player != null && heartbeat[i] == 0)
                {
                    //a dead player, kick him
                    positions[i].player = null;
                    kick++;
                }
            }
            if (kick > 0)
            {
                return false;
            }
            return true;
        }

        void CountDownTimerMethod(object o)
        {
            countDownTimerCount--;
            if (countDownTimerCount <= 0)
            {
                countDownTimer.Dispose();
                countDownTimer = null;
                if (CheckHeartbeat())
                {
                    state = ROOM_STATE.IN_GAME;
                    game = new Game(this);
                }
                else
                {
                    //kick someone
                    state = ROOM_STATE.WAITING;
                }
            }
        }

        void StopCountDown()
        {
            countDownTimer.Dispose();
            countDownTimer = null;
            state = ROOM_STATE.WAITING;
        }

        void UpdateCountDown()
        { 
            int count = 0;
            int count1 = 0;
            int count2 = 0;

            if (state == ROOM_STATE.IN_GAME)
            {
                return;
            }
            for (int i = 0; i < 6; i++)
            {
                if (positions[i].player != null)
                {
                    count++;
                    if (i < 3)
                    {
                        count1++;
                    }
                    else
                    {
                        count2++;
                    }
                }
            }
            if (count == 6)
            {
                if (playerCount != count)
                {
                    // the 6th just coming
                    StartCountDown();
                }
            }
            else if (count == 4 && type == ROOM_TYPE.ROOM_GAME)
            {
                if (playerCount != count)
                {
                    if (count1 == count2)
                    {
                        //same count for 2 party, ok for a 4p game
                        StartCountDown();
                    }
                }
            }
            else
            {
                if (state == ROOM_STATE.COUNT_DOWN)
                {
                    // someone come or go during count down
                    StopCountDown();
                }
            }
            playerCount = count;
        }

        public Boolean RoomProcessMessage(RoomMessageReq req)
        {
            Boolean ret = false;
            Position pos = null;

            UpdateHeartbeat(req.usrId);
            if (req.usrPos >= 0 && req.usrPos <= 5)
            {
                pos = positions[req.usrPos];
            }
            Position sitPos = null;
            if (req.sitPos >= 0 && req.sitPos <= 5)
            {
                sitPos = positions[req.sitPos];
            }
            switch (req.cmd)
            {
                case ROOM_CMD.GET_ROOM_STATE:
                    ret = true;
                    break;
                case ROOM_CMD.SET_USR_POSITION:
                    if (pos.player == null)
                    {
                        using (var redis = RedisMgr.Instance.GetClient())
                        {
                            IRedisTypedClient<Player> redisT = redis.As<Player>();
                            Player player = redisT.GetFromHash(req.usrId);
                            pos.player = player;
                            Console.WriteLine("player " + player.Id + "point="+ player.Points+",sit down");
                        }
                        if (sitPos != null)
                        {
                            sitPos.player = null;
                        }
                        ret = true;
                    }
                    else
                    {
                        ret = false;
                    }
                    break;
                case ROOM_CMD.START_GAME:
                    break;
                case ROOM_CMD.QUIT_ROOM:
                    if (state == ROOM_STATE.IN_GAME && sitPos != null)
                    {
                        //refuse to quit during game
                        ret = false;
                    }
                    else
                    {
                        if (sitPos != null)
                        {
                            sitPos.player = null;
                        }
                        ret = true;
                    }
                    break;
                default:
                    break;
            }
            UpdateCountDown();
            return ret;
        }
    }
}
